/**
 * @file XMen_asn1.h
 * @brief ASN.1 encoding and decoding library for SM2 cryptography
 * This header file provides functions for ASN.1 DER encoding and decoding,
 * specifically designed for use with SM2 cryptographic operations.
 */

#ifndef EASY_XMEN_ASN1_H
#define EASY_XMEN_ASN1_H

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

/**
 * @brief Maximum value for 32-bit signed integer
 */

#define XMEN_INT_MAX   2147483647


/**
 * @brief Get 32-bit unsigned integer from byte array (big endian)
 */

#define XMEN_GETU32(p) \
((uint32_t)(p)[0] << 24 | \
(uint32_t)(p)[1] << 16 | \
(uint32_t)(p)[2] <<  8 | \
(uint32_t)(p)[3])

/**
 * @brief Put 32-bit unsigned integer to byte array (big endian)
 */

#define XMEN_PUTU32(p,V) \
((p)[0] = (uint8_t)((V) >> 24), \
(p)[1] = (uint8_t)((V) >> 16), \
(p)[2] = (uint8_t)((V) >>  8), \
(p)[3] = (uint8_t)(V))


enum XMEN_ASN1_TAG {
    ASN1_TAG_BOOLEAN = 1,
    ASN1_TAG_INTEGER = 2,
    ASN1_TAG_BIT_STRING = 3,
    ASN1_TAG_OCTET_STRING = 4,
    ASN1_TAG_NULL = 5,
    ASN1_TAG_OBJECT_IDENTIFIER = 6,
    ASN1_TAG_ObjectDescriptor = 7,
    ASN1_TAG_EXTERNAL = 8,
    ASN1_TAG_REAL = 9,
    ASN1_TAG_ENUMERATED = 10, ASN1_TAG_EMBEDDED = 11, ASN1_TAG_UTF8String = 12, ASN1_TAG_RELATIVE_OID = 13, ASN1_TAG_NumericString = 18, ASN1_TAG_PrintableString = 19, ASN1_TAG_TeletexString = 20, ASN1_TAG_VideotexString = 21, ASN1_TAG_IA5String = 22, ASN1_TAG_UTCTime = 23, ASN1_TAG_GeneralizedTime = 24, ASN1_TAG_GraphicString = 25, ASN1_TAG_VisibleString = 26, ASN1_TAG_GeneralString = 27, ASN1_TAG_UniversalString = 28, ASN1_TAG_CHARACTER_STRING = 29, ASN1_TAG_BMPString = 30, ASN1_TAG_SEQUENCE = 0x30,
    ASN1_TAG_SET = 0x31,
    ASN1_TAG_EXPLICIT = 0xa0,
};



int EasyXmen_SM2_Asn1_Len2Der(uint32_t dlen, uint8_t** out, uint32_t* outlen);


int EasyXmen_SM2_Asn1_Der2Len(uint32_t* dlen, const uint8_t** in, uint32_t* inlen);


int EasyXmen_SM2_Asn1_LenIsZero(uint32_t len);


int EasyXmen_SM2_Asn1_LenCmp(uint32_t len1, uint32_t len2);


int EasyXmen_SM2_Asn1_Der2Type(int tag, const uint8_t** d, uint32_t* dlen, const uint8_t** in, uint32_t* inlen);



int EasyXmen_SM2_Asn1_Int2Der(int tag, const uint8_t* d, uint32_t dlen, uint8_t** out, uint32_t* outlen);


int EasyXmen_SM2_Asn1_Der2Int(int tag, const uint8_t** d, uint32_t* dlen, const uint8_t** in, uint32_t* inlen);


#define XMen_lib_asn1_sm2_integer_to_der(d, dlen, out, outlen) \
EasyXmen_SM2_Asn1_Int2Der(ASN1_TAG_INTEGER, d, dlen, out, outlen)


#define XMen_lib_asn1_sm2_integer_from_der(d, dlen, in, inlen) \
EasyXmen_SM2_Asn1_Der2Int(ASN1_TAG_INTEGER, d, dlen, in, inlen)


#define XMen_lib_asn1_sm2_sequence_from_der(d, dlen, in, inlen) \
EasyXmen_SM2_Asn1_Der2Type(ASN1_TAG_SEQUENCE, d, dlen, in, inlen)


int EasyXmen_SM2_Asn1_Head2Der(int tag, uint32_t dlen, uint8_t** out, uint32_t* outlen);


#define XMen_lib_asn1_sm2_sequence_header_to_der(dlen,out,outlen) EasyXmen_SM2_Asn1_Head2Der(ASN1_TAG_SEQUENCE,dlen,out,outlen)

#endif
